//
//  MCFileManager.m
//  FileOperationDemo
//
//  Created by Realank on 16/5/21.
//  Copyright © 2016年 iMooc. All rights reserved.
//

#import "MCFileManager.h"

@implementation MCFileManager


//获取沙盒根目录
+(NSString*)homeDirectory{
    return NSHomeDirectory();
}

//获取Documents目录
+(NSString*)documentsDirectory{
    /**
     *  获取Docments目录
     *
     *  @param NSDocumentDirectory 要搜索的目录
     *  @param NSUserDomainMask    要搜索的域，iOS中固定填写
     *  @param YES                 是否展开波浪号，iOS中固定填写
     *
     *  @return Documents目录
     */
    NSString* documentsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
    return documentsDir;
}

//获取Library目录
+(NSString*)libraryDirectory{
    
    /**
     *  获取Library目录
     *
     *  @param NSLibraryDirectory 要搜索的目录
     *  @param NSUserDomainMask   要搜索的域
     *  @param YES                是否展开波浪号
     *
     *  @return Library目录
     */
    NSString* libraryDir = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) firstObject];
    return libraryDir;
}

//获取Cache目录
+(NSString*)cacheDirectory{
    /**
     *  获取Cache目录
     *
     *  @param NSCachesDirectory 要搜索的目录
     *  @param NSUserDomainMask  要搜索的域
     *  @param YES               是否展开波浪号
     *
     *  @return Cache目录路径
     */
    NSString* cacheDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
    return cacheDir;
}

//获取tmp目录
+(NSString*)tmpDirectory{
    return NSTemporaryDirectory();
}

/**
 *  创建文件夹
 *
 *  @param path 要创建文件夹的上级路径
 *  @param name 要创建的文件夹名称
 *
 *  @return 是否创建成功
 */
+(BOOL)createDirectoryInPath:(NSString*)path directoryName:(NSString*)name{
    NSFileManager* fileManager = [NSFileManager defaultManager];
    NSString* newDirectory = [path stringByAppendingPathComponent:name];//创建新的文件夹路径
    //创建目录
    /**
     *  path : 要创建的文件夹的路径
     *  intermediateDirectories : 是否创建中间路径
     *  attributes : 传入nil表示使用默认属性
     *  error : 传入nil表示不获取失败原因
     */
    BOOL result = [fileManager createDirectoryAtPath:newDirectory withIntermediateDirectories:YES attributes:nil error:nil];
    if (result) {
        //文件创建成功
        return YES;
    }else{
        //文件创建失败
        return NO;
    }
    
}

/**
 *  创建文件
 *
 *  @param path     要创建文件的上级路径
 *  @param fileName 要创建的文件名
 *
 *  @return 是否创建成功
 */
+(BOOL)createFileInPath:(NSString*)path fileName:(NSString*)fileName{
    //获取文件管理器
    NSFileManager* fileManager = [NSFileManager defaultManager];
    //新文件的完整路径
    NSString* newFilePath = [path stringByAppendingPathComponent:fileName];
    /**
     *  创建文件
     *  path : 要创建文件的完整路径
     *  contents : 文件的内容，传入nil表示不添加任何内容
     *  attributes : 文件的属性，传入nil表示使用默认属性
     */
    BOOL result = [fileManager createFileAtPath:newFilePath contents:nil attributes:nil];
    if (result) {
        //文件创建成功
        return YES;
    }else{
        //文件创建失败
        return NO;
    }
}

/**
 *  查询文件/文件夹是否存在
 *
 *  @param path        要查询的路径
 *  @param isDirectory 输出参数，如果路径存在，这个路径是一个文件还是一个文件夹
 *
 *  @return 返回文件/文件夹是否存在
 */
+(BOOL)fileExistInPath:(NSString*)path isDirectory:(BOOL *)isDirectory{
    //获取文件管理器
    NSFileManager* fileManager = [NSFileManager defaultManager];
    /**
     *  查询文件/文件夹是否存在
     *  path : 要查询的路径
     *  isDirectory : 如果路径存在，这个路径是一个文件还是一个文件夹（输出参数）
     */
    BOOL exist = [fileManager fileExistsAtPath:path isDirectory:isDirectory];
    if (exist) {
        //文件或文件夹存在
        return YES;
    }else{
        //文件或文件夹不存在
        return NO;
    }
    
}

/**
 *  从指定路径读取文件内容字符串
 *
 *  @param path 文件的路径
 *
 *  @return 文件的内容
 */
+ (NSString*)readFileFromPath:(NSString*)path{
    
    /**
     *  path: 文件的路径
     *  encoding: 文件的编码格式
     *  error: 输出参数，返回错误原因
     *  返回值: 读取到的文件内容字符串
     */
    NSString* content = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
    return content;
}

/**
 *  写入字符串到文件（覆盖写）
 *
 *  @param content 要写入的内容
 *  @param path    要写入的文件的路径
 *
 *  @return 是否写入成功
 */
+ (BOOL)writeString:(NSString*)content toPath:(NSString*)path{
    
    /**
     *  path : 要写入文件的路径
     *  atomically : 是否安全读写
     *  encoding : 编码格式
     *  error : 输出参数，输出错误的原因
     */
    BOOL result = [content writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:nil];
    if (result) {
        //文件写入成功
        return YES;
    }else{
        //文件写入失败;
        return NO;
    }
}

/**
 *  读取文件(使用NSFileHandle)
 *
 *  @param path 文件的路径
 *
 *  @return 文件的内容字符串
 */
+ (NSString*)readFileUsingFileHandleFromPath:(NSString*)path{
    NSFileHandle* file = [NSFileHandle fileHandleForReadingAtPath:path];
    if (file) {
        NSData* content = [file readDataToEndOfFile];
        [file closeFile];
        NSString* contentString = [[NSString alloc]initWithData:content encoding:NSUTF8StringEncoding];
        return contentString;
    }
    return nil;
}

/**
 *  覆盖写文件(使用NSFilfHandle)
 *
 *  @param content 要写入的内容
 *  @param path    写入的文件路径
 *
 *  @return 写入是否成功
 */
+(BOOL)writeStringUsingFileHandle:(NSString*)content toPath:(NSString*)path{
    if (![self fileExistInPath:path isDirectory:nil]) {
        //文件不存在，创建这个文件
        BOOL result = [[NSFileManager defaultManager] createFileAtPath:path contents:nil attributes:nil];
        if (result == NO) {
            return NO;
        }
    }
    //获取FileHandle实例，对文件进行操作
    NSFileHandle* file = [NSFileHandle fileHandleForWritingAtPath:path];
    if (file) {
        NSData* dataContent = [content dataUsingEncoding:NSUTF8StringEncoding];
        [file truncateFileAtOffset:0];//清空文件内容
        [file writeData:dataContent];//写入文件
        [file closeFile];//关闭文件
        return YES;
    }
    return NO;
}

/**
 *  追加文件内容
 *
 *  @param content 要追加的文件内容
 *  @param path    文件的路径
 *
 *  @return 文件是否写入成功
 */
+(BOOL)appendStringUsingFileHandle:(NSString*)content toPath:(NSString*)path{
    if (![self fileExistInPath:path isDirectory:nil]) {
        //文件不存在，创建这个文件
        BOOL result = [[NSFileManager defaultManager] createFileAtPath:path contents:nil attributes:nil];
        if (result == NO) {
            return NO;
        }
    }
    //获取FileHandle实例，对文件进行操作
    NSFileHandle* file = [NSFileHandle fileHandleForWritingAtPath:path];
    if (file) {
        NSData* dataContent = [content dataUsingEncoding:NSUTF8StringEncoding];
        [file seekToEndOfFile];//将文件操作的指针，指向文件的结尾
        [file writeData:dataContent];//写入文件
        [file closeFile];//关闭文件
        return YES;
    }
    return NO;
}

/**
 *  写入字典到文件
 *
 *  @param dict 要写入的字典
 *  @param path 要写入的路径
 *
 *  @return 是否写入成功
 */
+(BOOL)saveDictionary:(NSDictionary*)dict isPlistFileOfPath:(NSString*)path{
    //判断dict是否是有效的字典
    if (dict && [dict isKindOfClass:[NSDictionary class]]) {
        //dict有效
        return [dict writeToFile:path atomically:YES];
    }
    return NO;
}

/**
 *  从Plist文件中读取字典
 *
 *  @param path 文件的路径
 *
 *  @return 读取到的字典
 */
+(NSDictionary*)dictionaryInPlistFileOfPath:(NSString*)path{
    //判断文件是否存在
    if ([self fileExistInPath:path isDirectory:nil]) {
        //文件存在
        //读取文件
        NSDictionary* dict = [[NSDictionary alloc] initWithContentsOfFile:path];
        //判断读取到的dict实例是否有效
        if (dict && [dict isKindOfClass:[NSDictionary class]]) {
            return dict;
        }
    }
    return nil;
}

/**
 *  列出某个路径下所有的文件或文件夹
 *
 *  @param path 指定的路径
 *
 *  @return 这个路径下所有的文件和文件夹名称字符串数组
 */
+ (NSArray*)listForPath:(NSString*)path{
    return [[NSFileManager defaultManager]contentsOfDirectoryAtPath:path error:nil];
}
/**
 *  递归打印某个路径下所有的文件和文件夹
 *
 *  @param path  指定的路径
 *  @param level 打印时缩进的等级
 */
+ (void)recursionPrintListOfPath:(NSString*)path forLevel:(NSInteger)level{
    
    NSArray* fileList = [self listForPath:path];
    for (NSString* fileName in fileList) {
        //确定打印的缩进
        NSString* indent = @"";
        for (int i = 0; i < level; i++) {
            indent = [indent stringByAppendingString:@"..."];
        }
        //打印这个文件名／文件夹名
        NSLog(@"%@/%@",indent,fileName);
        NSString* filePath = [path stringByAppendingPathComponent:fileName];
        BOOL isDirectory;
        //判断路径是一个文件还是一个文件夹
        [self fileExistInPath:filePath isDirectory:&isDirectory];
        if (isDirectory) {
            //如果要打印的路径，是一个文件夹，则递归打印这个文件夹下所有的文件和文件夹
            [self recursionPrintListOfPath:filePath forLevel:level+1];
        }
        
    }
    
}
/**
 *  递归打印沙盒下所有的文件和文件夹
 */
+ (void) printHierachyOfSandBox{
    [self recursionPrintListOfPath:[self homeDirectory] forLevel:0];
}


/**
 *  格式化log到文件中
 *
 *  @param format log字符串的格式，方法有可变参数，用法与NSLog类似
 */
+ (void)logWithFormat:(NSString*)format, ...{
    va_list paramList;
    va_start(paramList, format);//初始化参数列表
    
    NSString* logString = [[NSString alloc]initWithFormat:format arguments:paramList];//生成格式化字符串
    NSString* logToStore = [logString stringByAppendingString:@"\n"];
    
    va_end(paramList);//释放paramList内存
    
    //生成log存储的文件路径
    NSString* logPath = [[self cacheDirectory] stringByAppendingPathComponent:@"log.txt"];
    //存储log，追加内容到log文件中
    BOOL writeResult = [self appendStringUsingFileHandle:logToStore toPath:logPath];
    if (writeResult) {
        //写入Log成功
        NSLog(@"%@",logString);
    }else{
        //写入log失败
        NSLog(@"写入log失败：%@",logString);
    }
}
@end












